home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / New System Software Extensions / QuickDraw™ GX v1.0ß2 / Interfaces & Libraries / graphics libraries / scaler library.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-29  |  14.3 KB  |  361 lines  |  [TEXT/MPS ]

  1. /*
  2. **  scaler library.c    -   Routines used to call gxFont scalers directly
  3. **
  4. **  Copyright 1992 Apple Computer, Inc.  All rights reserved.
  5. */
  6.  
  7. #include <Memory.h>         /* NewPtr(), DisposePtr() */
  8. #include <GestaltEqu.h>         /* For calling Gestalt() */
  9.  
  10. #include "components.h"         /* Component Manager declarations */
  11. #include "scaler types.h"           /* Scaler API declarations and definitions */
  12. #include "scaler library.h"     /* The library's decls and defs. */
  13.  
  14. enum {
  15.     kScalerOpenSelect = 0,                      /* Component scaler operation selectors */
  16.     kScalerNewFontSelect,
  17.     kScalerNewVariationSelect,
  18.     kScalerNewTransformationSelect,
  19.     kScalerNewGlyphSelect,
  20.     kScalerStreamFontSelect,
  21.     kScalerKernGlyphsSelect,
  22.     kScalerCloseSelect
  23. };
  24.  
  25. #define kComponentScalerType    'sclr'          /* Type-gxTag for gxFont scaler components */
  26. #define PostScalerError(c,e)    (((c)->PostErrorFunction != nil && (e) != scaler_no_problem)? (c)->PostErrorFunction((c),(e)),e: e)
  27.  
  28. typedef struct {
  29.     gxFontFormatTag       format;                 /* Font format the scaler supports */
  30.     Component       theScalerComponent;         /* Used to open the component scaler */
  31.     ComponentInstance   theOpenedScalerComponent;   /* Component scaler (if 0, needs opening)*/
  32. } scalerEntry, *scalerEntryPtr;                 /* Information associated with a component gxFont scaler */
  33.  
  34. typedef struct {
  35.     long                oldSeed;                    /* Component Mgr's instance seed */
  36.     long                numScalers;             /* Number of scalers in the list */
  37.     scalerEntry     entries[1];             /* The array of scalers */
  38. } scalerList, *scalerListPtr;                       /* Component gxFont scaler list structure */
  39.  
  40. static  scalerListPtr   theListOfScalers = nil;     /* The list (really an array) of all registered component scalers */
  41.  
  42. static  Boolean     FindComponentFontScalers(void);
  43. static  scalerError FindMatchingOpenScaler(ComponentInstance *theScaler, scalerContext *theContext);
  44. static  Boolean     FindComponentFontScalers(void);
  45. static  scalerListPtr   BuildScalerList(void);
  46. static  scalerEntryPtr  FindMatchingScaler(scalerListPtr theList, gxFontFormatTag format);
  47. static  scalerListPtr   UpdateScalerList(scalerListPtr oldList);
  48.  
  49. pascal ComponentResult ComponentFontScalerOpen(ComponentInstance c, scalerContext* context, scalerInfo* theInfo) \
  50.         = ComponentCallNow( kScalerOpenSelect, sizeof(scalerContext*)+sizeof(scalerInfo*) );
  51.         
  52. pascal ComponentResult ComponentFontScalerNewFont(ComponentInstance c, scalerContext* context, scalerFontInfo* info) \
  53.         = ComponentCallNow( kScalerNewFontSelect, sizeof(scalerContext*)+sizeof(scalerFontInfo*) );
  54.         
  55. pascal ComponentResult ComponentFontScalerNewVariation(ComponentInstance c, scalerContext* context, long count, const gxFontVariation variation[]) \
  56.         = ComponentCallNow( kScalerNewVariationSelect, sizeof(scalerContext*)+sizeof(long)+sizeof(gxFontVariation*) );
  57.         
  58. pascal ComponentResult ComponentFontScalerNewTransform(ComponentInstance c, scalerContext* context, const scalerTransform* trans, scalerTransformInfo* info) \
  59.         = ComponentCallNow( kScalerNewTransformationSelect, sizeof(scalerContext*)+sizeof(scalerTransform*)+sizeof(scalerTransformInfo*));
  60.         
  61. pascal ComponentResult ComponentFontScalerNewGlyph(ComponentInstance c, scalerContext* context, const scalerGlyph* glyph, scalerMetrics* theMetrics, scalerBitmap* bitImage, void* outlineData) \
  62.         = ComponentCallNow( kScalerNewGlyphSelect, sizeof(scalerContext*)+sizeof(scalerGlyph*)+sizeof(scalerMetrics*)+sizeof(scalerBitmap*)+sizeof(void*));
  63.  
  64. pascal ComponentResult ComponentScalerKernGlyphs(ComponentInstance c, scalerContext* context,  const scalerKerning* kerning, gxPoint deltas[], scalerKerningNote flags[], gxPoint locations[]) \
  65.         = ComponentCallNow( kScalerKernGlyphsSelect, sizeof(scalerContext*)+sizeof(scalerKerning* )+sizeof(gxPoint*)+sizeof(gxPoint*)+sizeof(unsigned short*) );
  66.             
  67. pascal ComponentResult ComponentFontScalerStreamFont(ComponentInstance c, scalerContext* context, scalerStream* Stream) \
  68.         = ComponentCallNow( kScalerStreamFontSelect, sizeof(scalerContext*)+sizeof(scalerStream*) );
  69.  
  70. pascal ComponentResult ComponentFontScalerClose(ComponentInstance c, scalerContext* context) \
  71.         = ComponentCallNow( kScalerCloseSelect, sizeof(scalerContext*) );
  72.  
  73. scalerError FontScalerOpen( scalerContext* context, scalerInfo* theInfo)
  74. {
  75.     scalerError error;
  76.     ComponentInstance   theOpenScaler;
  77.     
  78.     if (!context) return scaler_null_context;
  79.     
  80.     if (theListOfScalers == nil)
  81.         if (!FindComponentFontScalers())
  82.             return PostScalerError(context, scaler_unsupported_font_format);
  83.     
  84.     if (!(error = FindMatchingOpenScaler(&theOpenScaler, context))) {
  85.         error = ComponentFontScalerOpen(theOpenScaler, context, theInfo);
  86.     }
  87.     
  88.     return error;
  89. }
  90.  
  91. scalerError FontScalerClose( scalerContext* context)
  92. {
  93.     scalerError error;
  94.     ComponentInstance   theOpenScaler;
  95.     
  96.     if (!context) return scaler_null_context;
  97.  
  98.     if (!(error = FindMatchingOpenScaler(&theOpenScaler, context))) {
  99.         error = ComponentFontScalerClose(theOpenScaler, context);
  100.     }
  101.     
  102.     return error;
  103. }
  104.  
  105. scalerError FontScalerNewFont( scalerContext* context, scalerFontInfo* info)
  106. {
  107.     scalerError error;
  108.     ComponentInstance   theOpenScaler;
  109.     
  110.     if (!context) return scaler_null_context;
  111.  
  112.     if (!(error = FindMatchingOpenScaler(&theOpenScaler, context))) {
  113.         error = ComponentFontScalerNewFont(theOpenScaler, context, info);
  114.     }
  115.     
  116.     return error;
  117. }
  118.  
  119. scalerError FontScalerNewVariation( scalerContext* context, long count, const gxFontVariation variation[])
  120. {
  121.     scalerError error;
  122.     ComponentInstance   theOpenScaler;
  123.     
  124.     if (!context) return scaler_null_context;
  125.  
  126.     if (!(error = FindMatchingOpenScaler(&theOpenScaler, context))) {
  127.         error = ComponentFontScalerNewVariation(theOpenScaler, context, count, (gxFontVariation*)variation);
  128.     }
  129.     
  130.     return error;
  131. }
  132.  
  133. scalerError FontScalerNewTransform( scalerContext* context, const scalerTransform* trans, scalerTransformInfo* info)
  134. {
  135.     scalerError error;
  136.     ComponentInstance   theOpenScaler;
  137.     
  138.     if (!context) return scaler_null_context;
  139.  
  140.     if (!(error = FindMatchingOpenScaler(&theOpenScaler, context))) {
  141.         error = ComponentFontScalerNewTransform(theOpenScaler, context, trans, info);
  142.     }
  143.     
  144.     return error;
  145. }
  146.  
  147. scalerError FontScalerNewGlyph( scalerContext* context, const scalerGlyph* glyph, scalerMetrics* theMetrics, scalerBitmap* bitImage, void* outlineData)
  148. {
  149.     scalerError error;
  150.     ComponentInstance   theOpenScaler;
  151.     
  152.     if (!context) return scaler_null_context;
  153.  
  154.     if (!(error = FindMatchingOpenScaler(&theOpenScaler, context))) {
  155.         error = ComponentFontScalerNewGlyph(theOpenScaler, context, glyph, theMetrics, bitImage, outlineData);
  156.     }
  157.     
  158.     return error;
  159. }
  160.  
  161. scalerError FontScalerKernGlyphs( scalerContext* context, const scalerKerning* kerning, gxPoint deltas[], scalerKerningNote flags[], gxPoint locations[])
  162. {
  163.     scalerError error;
  164.     ComponentInstance   theOpenScaler;
  165.     
  166.     if (!context) return scaler_null_context;
  167.  
  168.     if (!(error = FindMatchingOpenScaler(&theOpenScaler, context))) {
  169.         error = ComponentScalerKernGlyphs(theOpenScaler, context,  kerning, deltas, flags, locations);
  170.     }
  171.     
  172.     return error;
  173. }
  174.  
  175. scalerError FontScalerStreamFont( scalerContext* context, scalerStream* stream)
  176. {
  177.     scalerError error;
  178.     ComponentInstance   theOpenScaler;
  179.     
  180.     if (!context) return scaler_null_context;
  181.  
  182.     if (!(error = FindMatchingOpenScaler(&theOpenScaler, context))) {
  183.         error = ComponentFontScalerStreamFont(theOpenScaler, context, stream);
  184.     }
  185.     
  186.     return error;
  187. }
  188.  
  189. /*
  190. **  CloseAllOpenFontScalers()   -   Runs down the list of registered component scalers and closes the open ones.
  191. */
  192. void    CloseAllOpenFontScalers(void)
  193. {
  194.     if (theListOfScalers != nil) {
  195.         unsigned short  whichScaler;
  196.         
  197.         for (whichScaler = 0; whichScaler < theListOfScalers->numScalers; whichScaler++) {
  198.             if (theListOfScalers->entries[whichScaler].theOpenedScalerComponent != nil) {
  199.                 CloseComponent(theListOfScalers->entries[whichScaler].theOpenedScalerComponent);
  200.             }
  201.         }
  202.         
  203.         DisposePtr((Ptr)theListOfScalers);
  204.         theListOfScalers = nil;
  205.     }
  206. }
  207.  
  208. /*
  209. **  FindComponentFontScalers()  -   Called during the first ScalerOpen() call, this routine first determines whether the 
  210. **                          Component Manager is present.  If it is, it registers the built-in scalers and then
  211. **                          asks the Component Manager to find all of the registered scaler components.  A list
  212. **                          of these is built, and if all goes well the routine will return true, indicating that
  213. **                          component gxFont scalers are in use.  If it returns false, the built-in scalers will
  214. **                          need to be called directly.
  215. */
  216. static  Boolean FindComponentFontScalers()
  217. {
  218.     long    dummyLong;
  219.     
  220.     if (Gestalt(gestaltComponentMgr, &dummyLong) == 0) {
  221.         if (theListOfScalers = BuildScalerList()) {
  222.             return true;
  223.         }
  224.     }
  225.  
  226.     return false;
  227. }
  228.  
  229. /*
  230. **  FindMatchingScaler()    -   Given a gxFont format and the list of all registered component gxFont scalers, it looks for
  231. **                      a scaler (actually the first) that supports the format and returns the address of
  232. **                      its list entry.  It will return nil if no scaler is found for the format.
  233. */
  234. static  scalerEntryPtr  FindMatchingScaler(register scalerListPtr theList, gxFontFormatTag format)
  235. {
  236.     unsigned short  numScalers;
  237.     register scalerEntryPtr entry;
  238.     
  239.     numScalers = theList->numScalers;
  240.     entry = theList->entries;
  241.     do {
  242.         if (entry->format == format)
  243.             return entry;
  244.         entry++;
  245.     } while (--numScalers);
  246.     
  247.     return nil;
  248. }
  249.  
  250. /*
  251. **  UpdateScalerList()  -   Builds a new list of registered scalers in response to a changed component list
  252. **                      seed.  It copies from the old list the entries for those scalers that are in both lists.
  253. */
  254. static  scalerListPtr   UpdateScalerList(scalerListPtr oldList)
  255. {
  256.     scalerListPtr       newList;
  257.     unsigned short      whichScaler;
  258.     scalerEntryPtr      oldEntry;
  259.     
  260.     newList = BuildScalerList();        /* Create an all-new scaler list */
  261.     
  262.     /* We copy the entries from the old list for those scalers in both lists (they may be open)*/
  263.     for (whichScaler = 0; whichScaler < newList->numScalers; whichScaler++) {
  264.         if (oldEntry = FindMatchingScaler(oldList, newList->entries[whichScaler].format)) {
  265.             newList->entries[whichScaler] = *oldEntry;
  266.         }
  267.     }
  268.     
  269.     DisposePtr((Ptr)oldList);
  270.     theListOfScalers = newList;
  271.     
  272.     return newList;
  273. }
  274.  
  275. /*
  276. **  BuildScalerList()   -   Queries the Component Manager to find all currently registered component scalers.
  277. **                      It allocates and builds a list of these scalers.
  278. */
  279. static  scalerListPtr   BuildScalerList()
  280. {
  281.     long                    numScalers;
  282.     ComponentDescription    looking, theInfo;
  283.     register    scalerListPtr   newList = nil;
  284.     
  285.     /* Fill in the description structure */
  286.     looking.componentType           = kComponentScalerType;
  287.     looking.componentSubType            = kAnyComponentSubType;
  288.     looking.componentManufacturer       = kAnyComponentManufacturer;
  289.     looking.componentFlags          = 0;
  290.     looking.componentFlagsMask      = 0;
  291.     
  292.     /* Count the number of components and create our list based on that number*/
  293.     
  294.     numScalers = CountComponents(&looking);
  295.     
  296.     {   register scalerEntryPtr entry;
  297.         Component           lastComponent = 0, currentComponent;
  298.         
  299.         newList = (void*)NewPtr(sizeof(scalerList) + (numScalers - 1)*sizeof(scalerEntry));
  300.         
  301.         newList->oldSeed        = GetComponentListModSeed();
  302.         newList->numScalers = numScalers;
  303.             
  304.         /* For each scaler, get its info and remember the subtype, this is the format */
  305.         entry = newList->entries;
  306.         do {
  307.             currentComponent = FindNextComponent(lastComponent, &looking);
  308.         
  309.             if (GetComponentInfo(currentComponent,&theInfo, nil, nil, nil) == 0) {
  310.                 entry->format                   = theInfo.componentSubType;
  311.                 entry->theScalerComponent       = currentComponent;
  312.                 entry->theOpenedScalerComponent = nil;
  313.             } else
  314.                 entry->format = 0;  /* unusable scaler */
  315.                 
  316.             lastComponent = currentComponent;
  317.             entry++;
  318.         } while(--numScalers);
  319.     }
  320.     
  321.     return newList;
  322. }
  323.  
  324. /*
  325. **  FindMatchingOpenScaler()    -   This routine will look for a component scaler that supports the gxFont format
  326. **                          specified in the given scalerContext.  If necessary, the list of scalers will be
  327. **                          updated.  If a matching component scaler is found and is not open, the component
  328. **                          is opened.
  329. **
  330. **                          The routine returns scaler_no_problem if all went well,
  331. **                          scaler_unsupported_font_format if a component was not found or couldn't be
  332. **                          opened.
  333. **
  334. **                          If scaler_no_problem is returned *theOpenScaler will contain the
  335. **                          component instance for the desired scaler, else it will be undefined.
  336. */
  337. static  scalerError FindMatchingOpenScaler(ComponentInstance* theOpenScaler, scalerContext* theContext)
  338. {
  339.     scalerError result = scaler_no_problem;
  340.     scalerEntryPtr  theScaler;
  341.     
  342.     /* Check if a component was added while we were away, we may need to update the list of scalers */
  343.     if (GetComponentListModSeed() != theListOfScalers->oldSeed)
  344.         theListOfScalers = UpdateScalerList(theListOfScalers);
  345.         
  346.     theScaler = FindMatchingScaler(theListOfScalers, theContext->format);
  347.     
  348.     if (theScaler == nil) { 
  349.         result = scaler_unsupported_font_format;
  350.     } else {
  351.         if (theScaler->theOpenedScalerComponent == nil) {
  352.             if ((theScaler->theOpenedScalerComponent = OpenComponent(theScaler->theScalerComponent)) == nil)
  353.                 result = scaler_unsupported_font_format;
  354.         }
  355.         
  356.         *theOpenScaler = theScaler->theOpenedScalerComponent;
  357.     }
  358.     
  359.     return PostScalerError(theContext, result);
  360. }
  361.